<?php
/**
 * 系统区域控制器
 * 标准版：实现标准RESTful API接口
 * 
 * 负责处理地区相关的CRUD操作，包括省市区三级联动数据
 * 
 * @package app\controller\system
 * @author OA系统开发团队
 * @since 1.0.0
 */

declare (strict_types = 1);

namespace app\controller\system;

use app\BaseController;
use app\model\system\Region as RegionModel;
use app\service\RegionService;
use think\facade\Db;
use think\facade\Request;
use think\Response;

/**
 * 区域控制器类
 * 
 * 提供地区管理的核心功能，包括：
 * - 地区列表查询
 * - 树形结构数据获取
 * - 地区CRUD操作
 * - 级联选择器数据
 */
class Region extends BaseController
{
    /**
     * 获取地区列表
     * 
     * 支持分页查询，可按层级和父级ID筛选
     * 
     * @return \think\response\Json
     * 
     * @api {GET} /api/system/region 获取地区列表
     * @apiQuery {number} [level] 地区层级(1=省,2=市,3=区)
     * @apiQuery {number} [parent_id] 父级地区ID
     * @apiQuery {number} [page=1] 页码
     * @apiQuery {number} [limit=10] 每页数量
     * @apiSuccess {number} code 返回码
     * @apiSuccess {string} msg 返回消息
     * @apiSuccess {array} data.list 地区列表
     * @apiSuccess {number} data.total 总数量
     * @apiSuccess {number} data.page 当前页码
     * @apiSuccess {number} data.limit 每页数量
     */
    public function index(): Response
    {
        $param = Request::param();
        $level = (int)($param['level'] ?? 0);
        $parentId = (int)($param['parent_id'] ?? 0);
        $page = max(1, (int)($param['page'] ?? 1));
        $limit = max(1, min(100, (int)($param['limit'] ?? 10)));

        try {
            $query = RegionModel::where('parent_id', $parentId);

            if ($level > 0) {
                $query->where('level', $level);
            }

            $total = $query->count();

            $list = $query
                ->order('initial', 'asc')
                ->order('name', 'asc')
                ->page($page, $limit)
                ->select()
                ->toArray();

            if (!empty($list)) {
                $ids = array_column($list, 'id');
                $childrenCount = Db::name('region')
                    ->where('parent_id', 'in', $ids)
                    ->group('parent_id')
                    ->column('COUNT(*) as count', 'parent_id');

                foreach ($list as &$item) {
                    $count = (int)($childrenCount[$item['id']] ?? 0);
                    $item['has_children'] = $count > 0;
                    $item['children_count'] = $count;
                }
                unset($item);
            }

            return $this->paginate($list, $total, $page, $limit, '获取成功');
        } catch (\Exception $e) {
            return $this->error('获取地区列表失败', 500, 500, ['error' => $e->getMessage()]);
        }
    }
    
    /**
     * 获取树形结构地区列表
     * 
     * 获取完整的树形结构地区数据
     * 
     * @return \think\response\Json
     * 
     * @api {GET} /api/system/region/tree 获取树形地区列表
     * @apiQuery {number} [level] 地区层级(1=省,2=市,3=区)
     * @apiQuery {number} [parent_id] 父级地区ID
     * @apiSuccess {number} code 返回码
     * @apiSuccess {string} msg 返回消息
     * @apiSuccess {array} data 树形地区数据
     */
    public function tree(): Response
    {
        $param = Request::param();
        $level = (int)($param['level'] ?? 0);
        $parentId = (int)($param['parent_id'] ?? 0);

        try {
            $tree = RegionService::getRegionTree($level, $parentId);
            return $this->success($tree, '获取树形地区列表成功');
        } catch (\Exception $e) {
            return $this->error('获取树形地区列表失败', 500, 500, ['error' => $e->getMessage()]);
        }
    }
    
    /**
     * 查看地区详情
     * 
     * 获取指定ID的地区详细信息
     * 
     * @param int $id 地区ID
     * @return \think\response\Json
     * 
     * @api {GET} /api/system/region/:id 获取地区详情
     * @apiParam {number} id 地区ID
     * @apiSuccess {number} code 返回码
     * @apiSuccess {string} msg 返回消息
     * @apiSuccess {object} data 地区详情
     * @apiError 404 地区不存在
     */
    public function show(int $id): Response
    {
        if ($id <= 0) {
            return $this->paramError('地区ID必须是正整数');
        }

        try {
            $region = RegionModel::find($id);
            
            if (empty($region)) {
                return $this->error('地区不存在', 404);
            }

            $regionData = $region->toArray();
            
            // 处理经纬度数据
            $lngLat = $regionData['lng_lat'] ?? '';
            if (!empty($lngLat)) {
                $coords = explode(',', $lngLat);
                $regionData['longitude'] = trim($coords[0] ?? '');
                $regionData['latitude'] = trim($coords[1] ?? '');
            } else {
                $regionData['longitude'] = '';
                $regionData['latitude'] = '';
            }

            return $this->success($regionData, '获取地区详情成功');
        } catch (\Exception $e) {
            return $this->error('获取地区详情失败', 500, 500, ['error' => $e->getMessage()]);
        }
    }
    
    /**
     * 新增地区
     * 
     * 创建新的地区记录
     * 
     * @return \think\response\Json
     * 
     * @api {POST} /api/system/region 新增地区
     * @apiBody {string} name 地区名称
     * @apiBody {number} parent_id 父级地区ID(0表示顶级)
     * @apiBody {string} [initial] 首字母
     * @apiBody {string} [pinyin] 拼音
     * @apiBody {string} [citycode] 城市代码
     * @apiBody {string} [adcode] 行政代码
     * @apiBody {string} [lng_lat] 经纬度(格式: 经度,纬度)
     * @apiSuccess {number} code 返回码
     * @apiSuccess {string} msg 返回消息
     * @apiSuccess {object} data 创建的地区ID
     * @apiError 422 参数验证失败
     */
    public function create(): Response
    {
        $param = Request::param();
        
        // 参数验证
        $validate = $this->validate($param, [
            'name|地区名称' => 'require|max:50',
            'parent_id|父级地区ID' => 'require|integer|min:0',
            'initial|首字母' => 'max:10',
            'pinyin|拼音' => 'max:100',
            'citycode|城市代码' => 'max:20',
            'adcode|行政代码' => 'max:20',
            'lng_lat|经纬度' => 'max:50',
        ]);

        if ($validate !== true) {
            return $this->paramError($validate);
        }

        try {
            // 计算地区层级
            $level = 1;
            $parentId = (int)$param['parent_id'];
            
            if ($parentId > 0) {
                $parentRegion = RegionModel::find($parentId);
                if (empty($parentRegion)) {
                    return $this->paramError('父级地区不存在');
                }
                $parentLevel = (int)$parentRegion->getAttr('level');
                $level = $parentLevel + 1;
                
                // 限制最大层级为3级(省市区)
                if ($level > 3) {
                    return $this->paramError('地区层级不能超过3级');
                }
            }

            // 检查地区名称是否已存在(同级)
            $exists = RegionModel::where('parent_id', $parentId)
                ->where('name', $param['name'])
                ->find();
            
            if ($exists) {
                return $this->paramError('同级地区名称已存在');
            }

            $regionData = [
                'parent_id' => $parentId,
                'level' => $level,
                'name' => trim($param['name']),
                'initial' => trim($param['initial'] ?? ''),
                'pinyin' => trim($param['pinyin'] ?? ''),
                'citycode' => trim($param['citycode'] ?? ''),
                'adcode' => trim($param['adcode'] ?? ''),
                'lng_lat' => trim($param['lng_lat'] ?? ''),
                'create_time' => time(),
                'update_time' => time(),
            ];

            $region = RegionModel::create($regionData);
            RegionService::clearCache();

            return $this->created(['id' => $region->id], '地区创建成功');
        } catch (\Exception $e) {
            return $this->error('创建地区失败', 500, 500, ['error' => $e->getMessage()]);
        }
    }
    
    /**
     * 更新地区
     * 
     * 更新指定地区的详细信息
     * 
     * @return \think\response\Json
     * 
     * @api {PUT} /api/system/region 更新地区
     * @apiBody {number} id 地区ID
     * @apiBody {string} name 地区名称
     * @apiBody {number} parent_id 父级地区ID
     * @apiBody {string} [initial] 首字母
     * @apiBody {string} [pinyin] 拼音
     * @apiBody {string} [citycode] 城市代码
     * @apiBody {string} [adcode] 行政代码
     * @apiBody {string} [lng_lat] 经纬度
     * @apiSuccess {number} code 返回码
     * @apiSuccess {string} msg 返回消息
     * @apiError 404 地区不存在
     * @apiError 422 参数验证失败
     */
    public function update(): Response
    {
        $param = Request::param();
        
        // 参数验证
        $validate = $this->validate($param, [
            'id|地区ID' => 'require|integer|gt:0',
            'name|地区名称' => 'require|max:50',
            'parent_id|父级地区ID' => 'require|integer|min:0',
            'initial|首字母' => 'max:10',
            'pinyin|拼音' => 'max:100',
            'citycode|城市代码' => 'max:20',
            'adcode|行政代码' => 'max:20',
            'lng_lat|经纬度' => 'max:50',
        ]);

        if ($validate !== true) {
            return $this->paramError($validate);
        }

        try {
            $id = (int)$param['id'];
            $region = RegionModel::find($id);
            
            if (empty($region)) {
                return $this->error('地区不存在', 404);
            }

            $parentId = (int)$param['parent_id'];
            
            // 检查父级地区是否存在
            if ($parentId > 0) {
                $parentRegion = RegionModel::find($parentId);
                if (empty($parentRegion)) {
                    return $this->paramError('父级地区不存在');
                }
                
                // 检查是否尝试设置自身为父级
                if ($parentId === $id) {
                    return $this->paramError('地区不能设置自身为父级');
                }
                
                // 检查是否尝试设置子级为父级(会造成循环引用)
                $childrenIds = $this->getAllChildrenIds($id);
                if (in_array($parentId, $childrenIds)) {
                    return $this->paramError('不能将子级地区设置为父级');
                }
            }

            // 计算新的层级
            $level = 1;
            if ($parentId > 0) {
                $parentLevel = (int)$parentRegion->getAttr('level');
                $level = $parentLevel + 1;
                
                if ($level > 3) {
                    return $this->paramError('地区层级不能超过3级');
                }
            }

            // 检查地区名称是否已存在(同级，排除自身)
            $exists = RegionModel::where('parent_id', $parentId)
                ->where('name', $param['name'])
                ->where('id', '<>', $id)
                ->find();
            
            if ($exists) {
                return $this->paramError('同级地区名称已存在');
            }

            $updateData = [
                'parent_id' => $parentId,
                'level' => $level,
                'name' => trim($param['name']),
                'initial' => trim($param['initial'] ?? ''),
                'pinyin' => trim($param['pinyin'] ?? ''),
                'citycode' => trim($param['citycode'] ?? ''),
                'adcode' => trim($param['adcode'] ?? ''),
                'lng_lat' => trim($param['lng_lat'] ?? ''),
                'update_time' => time(),
            ];

            $region->save($updateData);
            RegionService::clearCache();

            return $this->success([], '地区更新成功');
        } catch (\Exception $e) {
            return $this->error('更新地区失败', 500, 500, ['error' => $e->getMessage()]);
        }
    }
    
    /**
     * 删除地区
     * 
     * 删除指定的地区记录，如果存在子地区则不允许删除
     * 
     * @return \think\response\Json
     * 
     * @api {DELETE} /api/system/region 删除地区
     * @apiBody {number} id 地区ID
     * @apiSuccess {number} code 返回码
     * @apiSuccess {string} msg 返回消息
     * @apiError 404 地区不存在
     * @apiError 422 存在子地区无法删除
     */
    public function delete(): Response
    {
        $param = Request::param();
        
        // 参数验证
        $validate = $this->validate($param, [
            'id|地区ID' => 'require|integer|gt:0',
        ]);

        if ($validate !== true) {
            return $this->paramError($validate);
        }

        try {
            $id = (int)$param['id'];
            $region = RegionModel::find($id);
            
            if (empty($region)) {
                return $this->error('地区不存在', 404);
            }
            
            // 检查是否有子地区
            $childCount = RegionModel::where('parent_id', $id)->count();
            if ($childCount > 0) {
                return $this->error('该地区存在子地区，无法删除', 422);
            }
            
            // 软删除地区
            $region->delete();
            RegionService::clearCache();
            
            return $this->success([], '地区删除成功');
        } catch (\Exception $e) {
            return $this->error('删除地区失败', 500, 500, ['error' => $e->getMessage()]);
        }
    }
    
    /**
     * 获取级联选择器数据
     * 
     * 获取适用于级联选择器的地区数据结构
     * 
     * @return \think\response\Json
     * 
     * @api {GET} /api/system/region/cascader 获取级联选择器数据
     * @apiQuery {number} [level] 地区层级(1=省,2=市,3=区)
     * @apiSuccess {number} code 返回码
     * @apiSuccess {string} msg 返回消息
     * @apiSuccess {array} data 级联选择器数据
     */
    public function cascader(): Response
    {
        $param = Request::param();
        $level = (int)($param['level'] ?? 0);
        
        try {
            $cascaderData = RegionModel::getCascaderData();
            
            if ($level > 0) {
                $cascaderData = $this->filterByLevel($cascaderData, $level);
            }
            
            return $this->success($cascaderData, '获取级联选择器数据成功');
        } catch (\Exception $e) {
            return $this->error('获取级联选择器数据失败', 500, 500, ['error' => $e->getMessage()]);
        }
    }
    
    /**
     * 根据层级过滤级联数据
     * 
     * @param array $data 原始级联数据
     * @param int $level 需要过滤到的层级
     * @return array 过滤后的级联数据
     */
    private function filterByLevel(array $data, int $level): array
    {
        $result = [];
        
        foreach ($data as $item) {
            if ($level >= 1) {
                $province = [
                    'value' => $item['value'],
                    'label' => $item['label']
                ];
                
                if ($level >= 2 && !empty($item['children'])) {
                    $province['children'] = [];
                    foreach ($item['children'] as $city) {
                        $cityData = [
                            'value' => $city['value'],
                            'label' => $city['label']
                        ];
                        
                        if ($level >= 3 && !empty($city['children'])) {
                            $cityData['children'] = [];
                            foreach ($city['children'] as $district) {
                                $cityData['children'][] = [
                                    'value' => $district['value'],
                                    'label' => $district['label']
                                ];
                            }
                        }
                        
                        $province['children'][] = $cityData;
                    }
                }
                
                $result[] = $province;
            }
        }
        
        return $result;
    }

    /**
     * 获取所有子地区ID(递归)
     * 
     * @param int $parentId 父级地区ID
     * @return array 所有子地区ID数组
     */
    private function getAllChildrenIds(int $parentId): array
    {
        $ids = [];
        $children = RegionModel::where('parent_id', $parentId)->column('id');
        
        foreach ($children as $childId) {
            $ids[] = $childId;
            // 递归获取所有子级
            $ids = array_merge($ids, $this->getAllChildrenIds($childId));
        }
        
        return $ids;
    }
}